package com.wxzz.elearing.comment.service.impl;

import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.wxzz.elearing.comment.dto.AnswersDto;
import com.wxzz.elearing.comment.dto.QuestionsAnswersDto;
import com.wxzz.elearing.comment.entity.Comment;
import com.wxzz.elearing.comment.entity.EnterpriseQuesAns;
import com.wxzz.elearing.comment.entity.QuestionsAnswersList;
import com.wxzz.elearing.comment.mapper.AdminEnterpriseQuesAnsMapper;
import com.wxzz.elearing.comment.mapper.BannedMapper;
import com.wxzz.elearing.comment.mapper.QuestionsAnswersListMapper;
import com.wxzz.elearing.comment.service.IQuestionsAnswersListService;
import com.wxzz.elearing.comment.service.openfeign.IWxPayFeign;
import com.wxzz.elearing.comment.service.openfeign.IWxUserApiFeign;
import com.wxzz.elearing.comment.vo.MyAnswerVo;
import com.wxzz.elearing.comment.vo.QuestionsAnswersListVo;
import com.wxzz.elearning.common.constants.OrderConstants;
import com.wxzz.elearning.common.constants.RedisConstants;
import com.wxzz.elearning.common.dto.FeignWxUserDto;
import com.wxzz.elearning.common.exception.ServiceException;
import com.wxzz.elearning.common.utils.CodeGenerateUtils;
import com.wxzz.elearning.common.utils.IPUtils;
import com.wxzz.elearning.common.vo.JgPageVo;
import com.wxzz.elearning.common.vo.ReturnVO;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.wxzz.elearing.comment.service.impl.GiveLikeServiceImpl.*;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author
 * @since 2021-05-14
 */
@Service
public class QuestionsAnswersListServiceImpl extends ServiceImpl<QuestionsAnswersListMapper, QuestionsAnswersList> implements IQuestionsAnswersListService {

    @Resource
    private QuestionsAnswersListMapper questionsAnswersListMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    public MongoTemplate mongoTemplate;

    @Autowired
    private IWxPayFeign iUserWalletApiFeign;

    @Autowired
    private IWxPayFeign wxPayFeign;

    @Resource
    private BannedMapper bannedMapper;
    @Resource
    private AdminEnterpriseQuesAnsMapper adminEnterpriseQuesAnsMapper;

    @Override
    @Transactional
    public ReturnVO<String> saveQuestionsAnswers(QuestionsAnswersList questionsAnswersList) {
        //接口幂等处理
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(RedisConstants.WX_USER_COMMENT + questionsAnswersList.getPublishPersonId(), questionsAnswersList.getPublishPersonId(), 5, TimeUnit.SECONDS);
        if (!Boolean.TRUE.equals(aBoolean)) {
            throw new ServiceException("请重新进入确认是否已经支付成功,以免重复支付");
        }
        //查询用户是否被封禁
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("user_id", questionsAnswersList.getPublishPersonId());
        queryWrapper.eq("module_type", 0);
        Integer integer = bannedMapper.selectCount(queryWrapper);
        if (integer > 0) {
            throw new ServiceException("您已被禁止发言");
        }

        Long publishPersonId = questionsAnswersList.getPublishPersonId();
        String publish = publishPersonId + ":draft";
        if (questionsAnswersList.getIsDraft() == 1) {
            redisTemplate.opsForHash().put(DRAFTINFO, publish, JSONObject.toJSONString(questionsAnswersList));
            return new ReturnVO("草稿保存成功", questionsAnswersList.getId());
        }

        List<String> publishImageUrlList = questionsAnswersList.getPublishImageUrlList();
        String s = JSONObject.toJSONString(publishImageUrlList);
        questionsAnswersList.setPublishImageUrl(s);
//        List list = JSONObject.parseObject(s, List.class);
        if (questionsAnswersList.getMoneyReward() != null && !questionsAnswersList.getMoneyReward().equals(new BigDecimal("0.00"))) {
            //调用支付模块 创建订单 赋值订单id 以下操作在支付成功回调中
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            Map<String, String> map = new HashMap();
            map.put("ipaddress", IPUtils.getIpAddr(request));
            map.put("wxUserId", String.valueOf(questionsAnswersList.getPublishPersonId()));
            map.put("serialid", CodeGenerateUtils.generateProductCode());
            map.put("payMoney", String.valueOf(questionsAnswersList.getMoneyReward()));
            map.put("modelType", OrderConstants.MODEL_TYPE_QUESTIONS_ANSWERS.toString());
            map.put("userType", OrderConstants.USER_TYPE_PLATFORM_WX.toString());
            map.put("orderTitle", "用户支付赏金id:" + questionsAnswersList.getId());
            Map<String, String> result = wxPayFeign.orderPay(map);//记录 undo_log
            questionsAnswersList.setOrderId(Long.valueOf(result.get("orderId")));
            questionsAnswersList.setIsPay(0);
            //插入发布记录到问答表
            questionsAnswersListMapper.insert(questionsAnswersList);
            //删除草稿
            redisTemplate.opsForHash().delete(DRAFTINFO, publish);
            //插入企业问答表
            EnterpriseQuesAns enterpriseQuesAns = new EnterpriseQuesAns();
            enterpriseQuesAns.setArticleId(questionsAnswersList.getId());
            enterpriseQuesAns.setEnterpriseId(questionsAnswersList.getEnterpriseId());
            enterpriseQuesAns.setPublishPerson(questionsAnswersList.getPublishPerson());
            enterpriseQuesAns.setPublishPersonId(questionsAnswersList.getPublishPersonId());
            adminEnterpriseQuesAnsMapper.insert(enterpriseQuesAns);
            return new ReturnVO("订单生成成功", result.get("returnJson"));
        } else {
            questionsAnswersList.setIsPay(1);
        }
        questionsAnswersListMapper.insert(questionsAnswersList);
        redisTemplate.opsForHash().delete(DRAFTINFO, publish);
        return new ReturnVO("发表问答成功", questionsAnswersList.getId());
    }

    @Autowired
    private IWxUserApiFeign iWxUserApiFeign;

    @Override
    public ReturnVO<JgPageVo<List<QuestionsAnswersListVo>>> queryQuestionsAnswersList(QuestionsAnswersDto questionsAnswersDto) {
        Page<Object> objects = PageHelper.startPage(questionsAnswersDto.getCurPage(), questionsAnswersDto.getMaxPage());
        QueryWrapper<QuestionsAnswersList> queryWrapper = new QueryWrapper();
        if (StringUtils.isNotBlank(questionsAnswersDto.getPublishContent())) {
            queryWrapper.like("publish_content", questionsAnswersDto.getPublishContent() + "%");
        }
        if (questionsAnswersDto.getPublishPersonId() != null && questionsAnswersDto.getPublishPersonId() != 0) {
            queryWrapper.eq("publish_person_id", questionsAnswersDto.getPublishPersonId());
        }
        if (questionsAnswersDto.getIsAccept() != null) {
            queryWrapper.eq("is_accept", questionsAnswersDto.getIsAccept());
        }
        if (questionsAnswersDto.getTitleType() != null && questionsAnswersDto.getTitleType() != 0) {
            queryWrapper.eq("title_type", questionsAnswersDto.getTitleType());
        }
        if (questionsAnswersDto.getEnterpriseId() != null && questionsAnswersDto.getEnterpriseId() != 0) {
            queryWrapper.eq("enterprise_id", questionsAnswersDto.getEnterpriseId());
        }
        if(StringUtils.isNotBlank(questionsAnswersDto.getCommonlyUsed())){
            Map<String, String> map = new HashMap<>();
            ReturnVO<List<Long>> listReturnVO;
            //远程调用查询用户列表
            map.put("nickname", questionsAnswersDto.getCommonlyUsed());
            listReturnVO = iWxUserApiFeign.listWxUserByMap(map);
            //若调用方没查到数据直接返回空数组
            if (listReturnVO.getData() != null && listReturnVO.getData().size() != 0) {
                queryWrapper.like("publish_content",questionsAnswersDto.getCommonlyUsed()).or().in("publish_person_id", listReturnVO.getData());
            } else {
                queryWrapper.like("publish_content",questionsAnswersDto.getCommonlyUsed());
            }
        }
        ReturnVO<List<Long>> listReturnVO;
        Map<String, String> map = new HashMap<>();
        if (StringUtils.isNotBlank(questionsAnswersDto.getPublishPerson())) {
            //远程调用查询用户列表
            map.put("nickname", questionsAnswersDto.getPublishPerson());
            listReturnVO = iWxUserApiFeign.listWxUserByMap(map);
//            queryWrapper.eq("publish_person", questionsAnswersDto.getPublishPerson());
            //若调用方没查到数据直接返回空数组
            if (listReturnVO.getData() != null && listReturnVO.getData().size() != 0) {
                queryWrapper.in("publish_person_id", listReturnVO.getData());
            } else {
                return new ReturnVO("问答列表查询成功", new JgPageVo<>(new PageInfo(Lists.newArrayList())));
            }
        }
        queryWrapper.eq("is_pay", 1);
        queryWrapper.orderByDesc("create_time");
        List<QuestionsAnswersList> questionsAnswersListList = questionsAnswersListMapper.selectList(queryWrapper);
        ArrayList<QuestionsAnswersListVo> questionsAnswersListVoArrayList = new ArrayList<>();

        questionsAnswersListList.forEach((questionsAnswersList) -> {
            FeignWxUserDto feignWxUserDto = iWxUserApiFeign.selectFeignWxUserDtoByWxUserId(questionsAnswersList.getPublishPersonId());
            questionsAnswersList.setIcon(feignWxUserDto.getIcon());
            questionsAnswersList.setPublishPerson(feignWxUserDto.getNickname());

            String publishImageUrl = questionsAnswersList.getPublishImageUrl();
            List<String> list = JSONObject.parseObject(publishImageUrl, List.class);
            questionsAnswersList.setPublishImageUrlList(list);
            QuestionsAnswersListVo temp = new QuestionsAnswersListVo();
            BeanUtils.copyProperties(questionsAnswersList, temp);
            questionsAnswersListVoArrayList.add(temp);
        });

        Map<String, String> entries = redisTemplate.opsForHash().entries(GIVELIKECOUNT);
        Map<String, String> entries2 = redisTemplate.opsForHash().entries(HEATCOUNT);
        questionsAnswersListVoArrayList.forEach((QuestionsAnswersListVo questionsAnswersListVo) -> {
            String artCount = questionsAnswersListVo.getId() + ":count";
            String s = entries.get(artCount);
            if (StringUtil.isNotBlank(s)) {
                int i = Integer.parseInt(s);
                questionsAnswersListVo.setGiveLikeCount(i);
            } else {
                questionsAnswersListVo.setGiveLikeCount(0);
            }
            Query query = new Query();
            query.addCriteria(Criteria.where("articleId").is(questionsAnswersListVo.getId()));
            questionsAnswersListVo.setAnswersCount(mongoTemplate.count(query, "commentCollection"));

            String heatCount = questionsAnswersListVo.getId() + ":heat";
            String heatNum = entries2.get(heatCount);
            if (StringUtil.isNotBlank(heatNum)) {
                int i = Integer.parseInt(heatNum);
                questionsAnswersListVo.setHeatCount(i);
            } else {
                questionsAnswersListVo.setHeatCount(0);
            }
        });
        long total = objects.getTotal();
        PageInfo pageInfo = new PageInfo(questionsAnswersListVoArrayList);
        pageInfo.setTotal(total);
        return new ReturnVO("问答列表查询成功", new JgPageVo<>(pageInfo));
//        Pageable pageable = PageRequest.of(questionsAnswersDto.getCurPage(), questionsAnswersDto.getMaxPage());
//        return new ReturnVO("问答列表查询成功", new JgPageVo<>(new PageInfo(questionsAnswersListVoArrayList)));
    }

    @Override
    public ReturnVO<QuestionsAnswersList> readDraft(QuestionsAnswersList questionsAnswers) {
        Map<String, String> entries = redisTemplate.opsForHash().entries(DRAFTINFO);
        String draft = questionsAnswers.getPublishPersonId() + ":draft";
        String str = entries.get(draft);
        JSONObject jsonObject = JSONObject.parseObject(str);
        QuestionsAnswersList questionsAnswersList = JSONObject.toJavaObject(jsonObject, QuestionsAnswersList.class);
        return new ReturnVO("查询草稿", questionsAnswersList);
    }

    @Override
    public ReturnVO<JgPageVo<List<MyAnswerVo>>> myAnswers(AnswersDto answersDto) {
        PageHelper.startPage(answersDto.getCurPage(), answersDto.getMaxPage());
        Query query = new Query();
        query.with(new Sort(Sort.Direction.DESC, "createTime"));
        query.addCriteria(Criteria.where("wxUserId").is(answersDto.getUid()));
        List<Comment> commentList = mongoTemplate.find(query, Comment.class);
        List<MyAnswerVo> myAnswerVoList = new ArrayList();
        //遍历该用户的评论列表
        commentList.forEach((model) -> {
            QuestionsAnswersList questionsAnswersList = questionsAnswersListMapper.selectById(model.getArticleId());
            MyAnswerVo myAnswerVo = new MyAnswerVo();
            BeanUtils.copyProperties(questionsAnswersList, myAnswerVo);
            //设置评论的图片
            String plPublishImageUrl = model.getPublishImageUrl();
            List<String> plImagesList = JSONObject.parseObject(plPublishImageUrl, List.class);
            myAnswerVo.setPlPublishImageUrlList(plImagesList);
            //设置文章的图片
            String publishImageUrl = questionsAnswersList.getPublishImageUrl();
//            String s = JSONObject.toJSONString(publishImageUrl);
            List<String> list = JSONObject.parseObject(publishImageUrl, List.class);
            myAnswerVo.setPublishImageUrlList(list);

            myAnswerVo.setCommentContent(model.getCommentContent());
            if (model.getUid() == questionsAnswersList.getAcceptId()) {
                myAnswerVo.setHaveAccept(1);
            } else {
                myAnswerVo.setHaveAccept(0);
            }

            Map<String, String> map = redisTemplate.opsForHash().entries(GIVELIKECOUNT);
            String artCount = model.getArticleId() + ":count";
            String s = map.get(artCount);
            if (StringUtil.isNotBlank(s)) {
                int i = Integer.parseInt(s);
                myAnswerVo.setGiveLikeCount(i);
            } else {
                myAnswerVo.setGiveLikeCount(0);
            }

            Map<String, String> map2 = redisTemplate.opsForHash().entries(HEATCOUNT);
            String heatCount = model.getArticleId() + ":heat";
            String hc = map2.get(heatCount);
            if (StringUtil.isNotBlank(hc)) {
                int i = Integer.parseInt(hc);
                myAnswerVo.setHeatCount(i);
            } else {
                myAnswerVo.setHeatCount(0);
            }

            Query queryCount = new Query();
            queryCount.addCriteria(Criteria.where("articleId").is(questionsAnswersList.getId()));
            long count = mongoTemplate.count(queryCount, "commentCollection");
            myAnswerVo.setAnswersCount(count);
            myAnswerVoList.add(myAnswerVo);
        });
        //获取已被采纳的答复
        List<Long> idList = new ArrayList<>();
        List<MyAnswerVo> answerVoList = new ArrayList();
        myAnswerVoList.forEach((myAnswerVo) -> {
            //判断id是否在id集合存在 不存在储存对象
            if (idList.contains(myAnswerVo.getId()) == false) {
                idList.add(myAnswerVo.getId());
                answerVoList.add(myAnswerVo);
            }
            //如果被采纳 就替换
            if (myAnswerVo.getHaveAccept() == 1) {
                int i = idList.indexOf(myAnswerVo.getId());
                answerVoList.add(i, myAnswerVo);
            }
        });
        return new ReturnVO("我的回答查询成功", new JgPageVo<>(new PageInfo(answerVoList)));
    }
}
